package com.qingzhuge.web.autoconfigure;

import com.qingzhuge.autoconfigure.QingTingProperties;
import com.qingzhuge.web.filter.CsrfFilter;
import com.qingzhuge.web.filter.XssFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import javax.servlet.DispatcherType;
import java.util.Collections;
import java.util.List;

/**
 * @author : zero.xiao
 * @description :
 * @date :2019-04-24 10:55
 * @modified :
 */
@Configuration
public class CorsCsrfXssConfiguration {
    @Autowired
    private QingTingProperties qingTingProperties;

    /**
     * 通过cors协议解决跨域问题,跨域访问CORS（Cross-Origin Resource Sharing）
     * 更细致也可以使用@CrossOrigin这个注解在controller类中使用。
     * 注解@CrossOrigin (origins = " http : / / 192.168.1.97 : 8080 ", maxAge = 3600)
     */
    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        if (qingTingProperties.getFilter().isCors()) {
            CorsConfiguration corsConfig = new CorsConfiguration();
            // 是否允许携带cookies
            corsConfig.setAllowCredentials(true);
            // 允许的请求源
            corsConfig.setAllowedOrigins(Collections.singletonList(CorsConfiguration.ALL));
            // 允许的http方法
            corsConfig.setAllowedMethods(Collections.singletonList(CorsConfiguration.ALL));
            // 允许的请求头
            corsConfig.setAllowedHeaders(Collections.singletonList(CorsConfiguration.ALL));
            // 预请求的存活有效期
            corsConfig.setMaxAge(3600L);
            //如果配置了corsAll=true，同时配置了corsUrls，则覆盖corsAll，开启指定url跨域访问
            if (qingTingProperties.getFilter().isCorsAll() && qingTingProperties.getFilter().getCorsUrls().size() < 1) {
                source.registerCorsConfiguration("/api/**", corsConfig);
            } else {
                source.registerCorsConfiguration("/api/sys/open/site", corsConfig);
                source.registerCorsConfiguration("/api/sys/login", corsConfig);
                List<String> corsUrls = qingTingProperties.getFilter().getCorsUrls();
                corsUrls.forEach(url -> source.registerCorsConfiguration(url, corsConfig));
            }
        }
        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return bean;
    }


    /**
     * CSRF（Cross Site Request Forgery），跨站点请求伪造。
     * CSRF攻击者在用户已经登录目标网站之后，诱使用户访问一个攻击页面，利用目标网站对用户的信任，
     * 以用户身份在攻击页面对目标网站发起伪造用户操作的请求，达到攻击目的。
     */
    @Bean
    public FilterRegistrationBean<CsrfFilter> csrfFilterRegistration(CsrfFilter csrfFilter) {
        FilterRegistrationBean<CsrfFilter> registration = new FilterRegistrationBean<>(csrfFilter);
        registration.setName("csrfFilter");
        registration.addUrlPatterns("/*");
        registration.setOrder(2);
        return registration;
    }

    /**
     * XSS 全称“跨站脚本”，是注入攻击的一种。其特点是不对服务器端造成任何伤害，而是通过一些正常的站内交互途径，
     * 例如发布评论，提交含有 JavaScript 的内容文本。这时服务器端如果没有过滤或转义掉这些脚本，作为内容发布到了页面上，
     * 其他用户访问这个页面的时候就会运行这些脚本。
     */
    @Bean
    public FilterRegistrationBean<XssFilter> xssFilterRegistration(XssFilter sssFilter) {
        FilterRegistrationBean<XssFilter> registration = new FilterRegistrationBean<>(sssFilter);
        registration.setDispatcherTypes(DispatcherType.REQUEST);
        registration.setOrder(Integer.MAX_VALUE);
        registration.setName("xssFilter");
        registration.addUrlPatterns("/*");
        registration.setOrder(3);
        return registration;
    }
}
